/*
 * Copyright (C) 2011, EADS France
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */
package xowl.interpreter.backends.rdf;

/**
 *
 * @author Laurent WOUTERS
 */
public class RDFTransformer implements xowl.interpreter.Transformer {
    private xowl.interpreter.impl.AggregatedEvaluator evaluator;
    private RDFRepository repository;
    private TranslatorXOWL_RDF translator;
    private RDFRuleEngine engine;
    private RDFChangeListener binding;
    private RDFChangeset master;
    
    public RDFTransformer(xowl.interpreter.impl.AggregatedEvaluator evaluator, RDFRepository repo, final xowl.interpreter.Transformation transformation, boolean bindMeta) {
        this.evaluator = evaluator;
        this.repository = repo;
        this.translator = repository.getXOWLTranslator();
        this.engine = new RDFRuleEngine(repository, new RDFChangeListener() {
            @Override public void onChange(xowl.interpreter.impl.AggregatedEvaluator evaluator, RDFChange change) { master.add(change); }
            @Override public void onChanges(xowl.interpreter.impl.AggregatedEvaluator evaluator, RDFChangeset changeset) {
                for (RDFChange change : changeset.getRDFChanges())
                    master.add(change);
            }
        });
        this.engine.addRules(evaluator, transformation.getInputOntology(), transformation.getTargetOntology(), transformation.getMetaOntology(), transformation.getRuleset());
        if (bindMeta) {
            binding = new RDFChangeListener() {
                @Override public void onChange(xowl.interpreter.impl.AggregatedEvaluator evaluator, RDFChange change) {
                    if (change.getOntology() == transformation.getMetaOntology())
                        engine.onChange(evaluator, change);
                }
                @Override public void onChanges(xowl.interpreter.impl.AggregatedEvaluator evaluator, RDFChangeset changeset) {
                    RDFChangeset filtered = new RDFChangeset();
                    for (RDFChange change : changeset.getRDFChanges())
                        if (change.getOntology() == transformation.getMetaOntology())
                            filtered.add(change);
                    engine.onChanges(evaluator, changeset);
                }
            };
            repository.getGraph().addEventHandler(binding, 1);
        }  
    }
    
    @Override public xowl.interpreter.Changeset tranform(xowl.interpreter.Changeset input) throws xowl.interpreter.XOWLException {
        master = new RDFChangeset();
        RDFChangeset changeset = null;
        if (input instanceof RDFChangeset) {
            changeset = (RDFChangeset)input;
        } else {
            changeset = new RDFChangeset();
            for (xowl.interpreter.Change change : input.getChanges()) {
                Translation translation = translator.translateAxiom(evaluator, null, true, true, change.getAxiom());
                for (RDFTriple triple : translation.getTriples())
                    changeset.add(new RDFChange(triple, change.getOntology(), change.isAdd()));
            }
        }
        engine.onChanges(evaluator, changeset);
        RDFChangeset result = master;
        master = new RDFChangeset();
        engine.onChanges(evaluator, changeset.getNegative());
        master = new RDFChangeset();
        return result;
    }
    
    @Override public void delete() {
        if (binding != null)
            repository.getGraph().removeEventHandler(binding);
    }
}
